import 'package:flutter/material.dart';
import 'package:get/get.dart';

class ScatterChart extends StatefulWidget {
  final double width;
  final double height;
  final Color? backgroundColor;
  final double maxY;
  final List<ScatterPoint>? points;
  final bool isShowY;
  final double rate;
  final double squareWidth;
  final Color referenceColor;
  final TextStyle xTextStyle;
  final TextStyle dialogTextStyle;
  final Function(int x)? onClick;

  const ScatterChart(
      {super.key,
      this.width = 500,
      this.height = 300,
      this.backgroundColor,
      this.maxY = 100,
      this.points,
      this.isShowY = false,
      this.rate = 1,
      this.squareWidth = 9,
      this.referenceColor = Colors.grey,
      this.xTextStyle = const TextStyle(),
      this.dialogTextStyle = const TextStyle(),
      this.onClick});

  @override
  State<StatefulWidget> createState() => _ScatterChartState();
}

class _ScatterChartState extends State<ScatterChart> {
  double globPositionX = 0;
  double globPositionY = 0;

  int? selectedPointIndex;

  double? verticalLineX; // 用于存储竖线的X坐标

  List<double> horizontalReferenceLines = [0, 0.25, 0.5, 0.75, 1];

  OverlayEntry? _overlayEntry;

  @override
  void dispose() {
    super.dispose();
    _removeOverlay();
  }

  _removeOverlay() {
    if (_overlayEntry != null) {
      _overlayEntry?.remove();
      _overlayEntry = null;
    }
  }

  void handleTap(Offset tapPosition, Size size, bool isPointerExit) {
    if (isPointerExit) {
      _removeOverlay();
      setState(() {
        selectedPointIndex = null;
        verticalLineX = null; // 清除竖线
      });
      return;
    }
    setState(() {
      verticalLineX = tapPosition.dx.clamp(0, size.width); // 确保竖线在图表区域内

      if (verticalLineX! > tapPosition.dx.clamp(size.width, Get.width)) {
        if (_overlayEntry != null) {
          _overlayEntry?.remove();
          _overlayEntry = null;
          return;
        } // 移除弹出窗口
      }
    });

    for (int i = 0; i < widget.points!.length; i++) {
      double y = widget.points![i].y;
      double xCoord =
          (size.width / (widget.points!.length + 1)) * (i + 1); // 映射x到画布
      double yCoord = size.height * widget.rate -
          (widget.points![i].y / 100.0) * y; // 映射y到画布

      Offset point = Offset(xCoord, yCoord);

      verticalLineX = xCoord; // 设置竖线的位置

      print('size: ${size.width * 0.07}');
      if ((tapPosition.dx - point.dx).abs() <= size.width * 0.07) {
        setState(() {
          selectedPointIndex = i;
          // verticalLineX = xCoord; // 设置竖线的位置
        });
        // 创建并显示自定义弹出窗口
        final RenderBox renderBox = context.findRenderObject() as RenderBox;
        final Offset globalPosition = renderBox.localToGlobal(point);
        ScatterPoint scatterPoint = widget.points![i];
        double left =
            globalPosition.dx - widget.width * 0.26 + size.width * 0.3;
        // if (i <= widget.points!.length - 1 && i >= widget.points!.length - 3) {
        //   left = globalPosition.dx - widget.width * 0.56;
        // }
        WidgetsBinding.instance.addPostFrameCallback((_) {
          _showPopup(xCoord, tapPosition, context, widget.points!, left);
        });
        return;
      }
    }
  }

  _showPopup(double xCoord, Offset position, BuildContext context,
      List<ScatterPoint> points, double left) {
    if (selectedPointIndex == null) {
      return;
    }
    final scatterPoint = points[selectedPointIndex!];

    // 获取渲染上下文
    final RenderBox renderBox = context.findRenderObject() as RenderBox;
    final Offset globalPosition = renderBox.localToGlobal(position);

    // 创建自定义弹出窗口
    _removeOverlay();

    _overlayEntry = OverlayEntry(builder: (context) {
      return Positioned(
          left: left,
          top: globalPosition.dy - 40, // 调整弹出窗口的位置
          child: Material(
            color: Colors.transparent,
            child: InkWell(
              onTap: () {
                _overlayEntry?.remove();
                _overlayEntry = null;
              },
              child: Container(
                padding: const EdgeInsets.all(8.0),
                width: widget.width * 0.5,
                decoration: BoxDecoration(
                  color: Colors.black.withAlpha(150),
                  borderRadius: BorderRadius.circular(8.0),
                  boxShadow: [
                    BoxShadow(
                      color: Colors.black.withOpacity(0.2),
                      blurRadius: 4.0,
                      spreadRadius: 2.0,
                    ),
                  ],
                ),
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      '第' + scatterPoint.x.toString() + '手',
                      style: widget.dialogTextStyle,
                    ),
                    Text(
                      '胜率' + scatterPoint.wrs,
                      style: widget.dialogTextStyle,
                    ),
                    Text(
                      '目差' + scatterPoint.wss.toString(),
                      style: widget.dialogTextStyle,
                    )
                  ],
                ),
              ),
            ),
          ));
    });

    // 显示弹出窗口
    Overlay.of(context).insert(_overlayEntry!);
  }

  @override
  Widget build(BuildContext context) {
    return Container(
        color: widget.backgroundColor ?? Colors.transparent,
        height: widget.height + 20,
        child: GestureDetector(
            behavior: HitTestBehavior.opaque,
            onTapDown: (event) {
              if (selectedPointIndex != null) {
                widget.onClick?.call(selectedPointIndex!);
              }
              handleTap(event.localPosition, Size(widget.width, widget.height),
                  false);
            },
            child: MouseRegion(
                onHover: (event) {
                  handleTap(event.localPosition,
                      Size(widget.width, widget.height), false);
                },
                onExit: (event) {
                  handleTap(event.localPosition,
                      Size(widget.width, widget.height), true);
                },
                child: Column(
                  children: [
                    CustomPaint(
                        size: Size(widget.width, widget.height),
                        painter: Chart(
                            widget.points!,
                            widget.maxY,
                            widget.isShowY,
                            widget.rate,
                            widget.squareWidth,
                            verticalLineX,
                            horizontalReferenceLines,
                            widget.referenceColor)),
                    CustomPaint(
                        size: Size(widget.width, 2),
                        painter: NumChart(widget.points!, widget.xTextStyle)),
                  ],
                ))));
  }
}

class Chart extends CustomPainter {
  final List<ScatterPoint> points;
  final double maxY;
  final bool isShowY;
  final double rate;
  final double squareWidth;
  final double? verticalLineX; // 用于绘制竖线
  final List<double> horizontalReferenceLines;
  final Color referenceColor;

  const Chart(this.points, this.maxY, this.isShowY, this.rate, this.squareWidth,
      this.verticalLineX, this.horizontalReferenceLines, this.referenceColor);

  @override
  void paint(Canvas canvas, Size size) {
    final axisPaint = Paint()
      ..color = Colors.black
      ..strokeWidth = 0.6
      ..style = PaintingStyle.stroke;

    final textPainter = TextPainter(
      textDirection: TextDirection.ltr,
      textAlign: TextAlign.center,
    );

    // X轴
    canvas.drawLine(Offset(0, size.height * rate),
        Offset(size.width, size.height * rate), axisPaint);

    List<Offset> data = points.map((it) {
      int index = points.indexOf(it);
      double y = it.y; // 获取对应的y值
      double xCoord =
          (size.width / (points.length + 1)) * (index + 1); // 映射x到画布
      double yCoord =
          size.height * 0.5 - (size.height * 0.5 / maxY) * y; // 映射y到画布
      return Offset(xCoord, yCoord);
    }).toList();

    // 添加X轴刻度标记
    for (int i = 0; i < data.length; i++) {
      double x = data[i].dx;
      canvas.drawLine(Offset(x, size.height * rate),
          Offset(x, size.height * rate), axisPaint);
      // textPainter.text = TextSpan(
      //     text: '${points[i].x}',
      //     style: const TextStyle(color: Colors.black, fontSize: 12));
      // textPainter.layout();
      // textPainter.paint(
      //     canvas, Offset(x - textPainter.width / 2, size.height * rate + 2));
    }

    if (isShowY) {
      // Y轴
      canvas.drawLine(
          const Offset(0, 0), Offset(0, size.height * rate), axisPaint);

      // 添加Y轴刻度标记
      for (int i = 0; i <= 10; i++) {
        double y = size.height * rate - (size.height * rate / 10 * i);
        canvas.drawLine(Offset(0, y), Offset(-5, y), axisPaint);
        textPainter.text = TextSpan(
            text: '${i * 10}',
            style: const TextStyle(color: Colors.black, fontSize: 12));
        textPainter.layout();
        textPainter.paint(
            canvas, Offset(-textPainter.width - 5, y + textPainter.height + 2));
      }
    }

    // 绘制水平参考线
    for (double refY in horizontalReferenceLines) {
      final yCoord = size.height - (refY * size.height);
      final paint = Paint()
        ..color = referenceColor
        ..strokeWidth = 0.2
        ..style = PaintingStyle.stroke
        ..strokeCap = StrokeCap.round
        ..isAntiAlias = true
        ..strokeJoin = StrokeJoin.round;
      canvas.drawLine(Offset(0, yCoord), Offset(size.width, yCoord), paint);
    }

    // 绘制竖线
    if (verticalLineX != null) {
      final dashPaint = Paint()
        ..color = Colors.white
        ..strokeWidth = 0.5
        ..style = PaintingStyle.stroke;

      const double dashWidth = 3.0;
      const double gapWidth = 3.0;
      double startX = 0.0;
      while (startX < size.height) {
        canvas.drawLine(
          Offset(verticalLineX!, startX),
          Offset(verticalLineX!, startX + dashWidth),
          dashPaint,
        );
        startX += dashWidth + gapWidth;
      }
    }

    // 绘制曲线
    // for (int i = 0; i < data.length - 1; i++) {
    //   canvas.drawLine(data[i], data[i + 1], axisPaint);
    // }

    double space = 18;

    for (final element in points) {
      ScatterPoint scatterPoint = element;
      int index = points.indexOf(element);
      double y = element.y; // 获取对应的y值
      double xCoord =
          (size.width / (points.length + 1)) * (index + 1); // 映射x到画布
      double yCoord =
          size.height * rate - (size.height * rate / 100.0) * y; // 映射y到画布

      Offset point = Offset(xCoord, yCoord);

      int bw = element.color;
      Color color = bw == 1 ? Colors.black : Colors.white;

      final fillPaint = Paint()
        ..color = color
        ..style = PaintingStyle.fill;

      final circlePaint = Paint()
        ..color = scatterPoint.colorFlag
        ..style = PaintingStyle.fill;

      final strokePaint = Paint()
        ..color = color
        ..style = PaintingStyle.stroke
        ..strokeWidth = 2.0; // 边界宽度

      double squareSize = squareWidth; // 方形的大小

      // 方形
      final squareTopLeft = Offset(point.dx - squareSize / 2,
          point.dy - squareSize * element.wrReduce / 20.0 - space);
      final squareRect = Rect.fromLTWH(
          squareTopLeft.dx,
          point.dy - squareSize * element.wrReduce / 20.0 - space,
          squareSize,
          squareSize * element.wrReduce / 20.0);

      canvas.drawRect(squareRect, fillPaint);

      // 箭头
      final path = Path();
      path.moveTo(point.dx - squareSize, point.dy - space); // 箭头左上角
      path.lineTo(point.dx + squareSize, point.dy - space); // 箭头右上角
      path.lineTo(point.dx, point.dy - 9); // 箭头底部中心
      path.close(); // 关闭路径
      canvas.drawPath(path, fillPaint);

      // 圆
      final circleCenter = point;
      const circleRadius = 7.0; // 圆的半径
      canvas.drawCircle(circleCenter, circleRadius, circlePaint);

      // 边界
      canvas.drawCircle(circleCenter, circleRadius, strokePaint);
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }
}

class NumChart extends CustomPainter {
  final List<ScatterPoint> points;
  final TextStyle textStyle;

  const NumChart(this.points, this.textStyle);

  @override
  void paint(Canvas canvas, Size size) {
    final textPainter = TextPainter(
      textDirection: TextDirection.ltr,
      textAlign: TextAlign.center,
    );
    List<Offset> data = points.map((it) {
      int index = points.indexOf(it);
      double y = it.y; // 获取对应的y值
      double xCoord =
          (size.width / (points.length + 1)) * (index + 1); // 映射x到画布
      double yCoord =
          size.height * 0.5 - (size.height * 0.5 / 100) * y; // 映射y到画布
      return Offset(xCoord, yCoord);
    }).toList();

    // 添加X轴刻度标记
    for (int i = 0; i < data.length; i++) {
      double x = data[i].dx;
      textPainter.text = TextSpan(text: '${points[i].x}', style: textStyle);
      textPainter.layout();
      textPainter.paint(
          canvas, Offset(x - textPainter.width / 2, size.height + 2));
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }
}

class ScatterPoint {
  int x = 0;
  double y = 0;
  double preWinRate;
  double wrReduce = 0;
  String wrs = '';
  String wss = '';
  int color = 0;
  Color colorFlag;

  ScatterPoint(this.x, this.y, this.preWinRate, this.wrReduce, this.wrs,
      this.wss, this.color, this.colorFlag);
}
